package fi.iki.joker.mobilogger;

import java.util.LinkedList;
import java.util.Map;

import fi.iki.joker.mobilogger.blogs.BlogConfigConstants;
import fi.iki.joker.mobilogger.blogs.BlogInterfaceFactory;
import fi.iki.joker.mobilogger.db.BlogConfigBean;
import fi.iki.joker.mobilogger.db.DBUtil;
import fi.iki.joker.mobilogger.db.ImageRepoBean;
import fi.iki.joker.mobilogger.img.ImageRepoInterfaceFactory;
import fi.iki.joker.mobilogger.img.ImageRepository;
import fi.iki.joker.mobilogger.img.ImageRepositoryConstants;
import fi.iki.joker.mobilogger.img.ImageRepositoryConstants.ImageRepositoryType;
import fi.iki.joker.mobilogger.util.AlertUtil;

import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.net.Uri;
import android.os.Bundle;
import android.text.Spannable;
import android.text.style.URLSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TableLayout;
import android.widget.AdapterView.OnItemSelectedListener;

/**
 * This Activity class is the main editor activity for Mobilogger image repository configs.
 * Supports creating, saving and updating these configurations.
 * @author FI41051
 *
 */

public class ImageRepoConfigEditor extends Activity implements OnItemSelectedListener, OnClickListener{

	private final String TAG = "ImageRepoConfigEditor";
	private final int DYNAMIC_FIELD_ID_LIMIT = 600;
	private int mState = 0;
	private int mOldConfigType = -1;
	private Uri mUri = null;
	private final int STATE_UPDATE = 1;
	private final int STATE_INSERT = 2;
	private final int STATE_DELETE = 3;
	DBUtil db = null;
	ImageRepoBean irb = null;
	ImageRepository ri;
	Spinner repotypes = null;
	
	public static class ConfigTitleText extends EditText {
        private Rect mRect;
        private Paint mPaint;

        // we need this constructor for ViewInflate
        public ConfigTitleText(Context context, AttributeSet attrs) {
            super(context, attrs);

            mRect = new Rect();
            mPaint = new Paint();
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setColor(0xFF0000FF);
        }

        @Override
        protected void onDraw(Canvas canvas) {

            int count = getLineCount();
            Rect r = mRect;
            Paint paint = mPaint;

            for (int i = 0; i < count; i++) {
                int baseline = getLineBounds(i, r);

                canvas.drawLine(r.left, baseline + 1, r.right, baseline + 1,
                                paint);
            }

            super.onDraw(canvas);
        }
        
    }
	
	public static class UsernameText extends EditText {
        private Rect mRect;
        private Paint mPaint;

        // we need this constructor for ViewInflate
        public UsernameText(Context context, AttributeSet attrs) {
            super(context, attrs);

            mRect = new Rect();
            mPaint = new Paint();
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setColor(0xFF0000FF);
        }

        @Override
        protected void onDraw(Canvas canvas) {

            int count = getLineCount();
            Rect r = mRect;
            Paint paint = mPaint;

            for (int i = 0; i < count; i++) {
                int baseline = getLineBounds(i, r);

                canvas.drawLine(r.left, baseline + 1, r.right, baseline + 1,
                                paint);
            }

            super.onDraw(canvas);
        }
        
    }
	
	public static class PasswordText extends EditText {
        private Rect mRect;
        private Paint mPaint;

        // we need this constructor for ViewInflate
        public PasswordText(Context context, AttributeSet attrs) {
            super(context, attrs);

            mRect = new Rect();
            mPaint = new Paint();
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setColor(0xFF0000FF);
        }

        @Override
        protected void onDraw(Canvas canvas) {

            int count = getLineCount();
            Rect r = mRect;
            Paint paint = mPaint;

            for (int i = 0; i < count; i++) {
                int baseline = getLineBounds(i, r);

                canvas.drawLine(r.left, baseline + 1, r.right, baseline + 1,
                                paint);
            }

            super.onDraw(canvas);
        }
        
    }
	
	@Override
	protected void onCreate(Bundle icicle) {
		// TODO Auto-generated method stub
		super.onCreate(icicle);
		setContentView(R.layout.imagerepoeditor);
		final Intent intent = getIntent();
		if(intent.getAction().equals(Intent.ACTION_INSERT)) {
			mState = STATE_INSERT;
		} else if(intent.getAction().equals(Intent.ACTION_EDIT)) {
			mState = STATE_UPDATE;
			mUri = intent.getData();
		} else if(intent.getAction().equals(Intent.ACTION_DELETE)) {
			mState = STATE_DELETE;
		}
		//create spinner where user can select the image repository type to create
		repotypes = (Spinner) findViewById(R.id.imagerepotypespinner);
		LinkedList<String> configs = ImageRepositoryConstants.getRepoTypeTitles();
		Object res = new ArrayAdapter(this,android.R.layout.simple_spinner_item,configs);
		ArrayAdapter<CharSequence> adapter = (ArrayAdapter<CharSequence>)res;
		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		repotypes.setAdapter(adapter);
		repotypes.setOnItemSelectedListener(this);
		repotypes.setSelection(0);
		switch(mState) {
		case STATE_INSERT:
			irb = new ImageRepoBean();
			irb.setInterfaceType(ImageRepositoryConstants.getInterfaceTypeId(ImageRepositoryConstants.ImageRepositoryType.PICASA_WEB));
			Button saveButton = (Button) findViewById(R.id.imagerepoconfig_save_button);
			saveButton.setOnClickListener(this);
			break;
		case STATE_UPDATE:
			//Load the updated bean from DB based on intent Uri.
			int configid = -1;
        	String id = mUri.getPath();
        	String temp = null;
        	if(id != null) {
        		try {
        			temp = id.substring(id.lastIndexOf('/')+1);
        			configid = Integer.parseInt(temp);
        		} catch (NumberFormatException ne) {
        			Log.e(TAG, "Unable to parse the Intent path id ("+temp+") into an integer!");
        		}
        	}
        	if(configid > 0) {
        		if(db == null) { 
        			db = new DBUtil();
        		}
        		irb = db.getImageRepository(this,configid);
        	}
			EditText username = (EditText)findViewById(R.id.imagerepo_username);
			EditText password = (EditText)findViewById(R.id.imagerepo_password);
			EditText title = (EditText)findViewById(R.id.imagerepo_title);
			username.setText(irb.getUsername());
			password.setText(irb.getPassword());
			title.setText(irb.getTitle());
			if(irb.getInterfaceType() == ImageRepositoryConstants.getInterfaceTypeId(ImageRepositoryType.PICASA_WEB)) {
				repotypes.setSelection(0);
			} else if(irb.getInterfaceType() == ImageRepositoryConstants.getInterfaceTypeId(ImageRepositoryType.FLICKR)) {
				repotypes.setSelection(1);
			}
			break;
		case STATE_DELETE:
			
			break;
		}
		
	}

	public void onItemSelected(AdapterView parent, View v, int position, long id) {
		removeConfigDependentFields();
		//the field numbering in the Linkedlist (arrayadapter) starts from 0, 
		//but the blog configuration numbering starts from 1. Thus +1.
		if(mState == STATE_INSERT) {
			irb.setInterfaceType(position+1);
			repotypes.setSelection(position);
			createConfigDependentFields(irb);
		} else if(mState == STATE_UPDATE && (position+1 == mOldConfigType)) {
			//user has changed to a blog config type for which we have already
			//some saved settings
			irb.setInterfaceType(position+1);
			repotypes.setSelection(position);
			createConfigDependentFields(irb);
		} else if(mState == STATE_UPDATE) {
			//user edits a blog config and changes to a new type for which we
			//don't have any settings saved.
			irb.setInterfaceType(position+1);
			repotypes.setSelection(position);
			createConfigDependentFields(irb);
		}
		
	}

	public void onNothingSelected(AdapterView arg0) {
		// TODO Auto-generated method stub
		repotypes.setSelection(0);
		irb.setInterfaceType(repotypes.getSelectedItemPosition()+1);
	}
	

	/**
	 * This calls into the class that represents the current interface to image repository thats being edited.
	 * It creates, with the help of this class, the GUI widgets of the editor which are specific to
	 * this particular type of repository configuration. The views created should have DYNAMIC_FIELD_ID_LIMIT 
	 * or larger number as their id.
	 * 
	 * @param repoBean The bean that represents the repository configuration 
	 */
	
	private void createConfigDependentFields(ImageRepoBean repoBean) {
		TableLayout table = (TableLayout)findViewById(R.id.repoconfigtablelayout);
    	//Call into the repository interface and have it create the proper GUI for 
		//It's configuration.
		ImageRepositoryConstants.ImageRepositoryType repotype = ImageRepositoryConstants.getInterfaceTypeEnum(irb.getInterfaceType());
		ri = ImageRepoInterfaceFactory.getInstance(repotype);
		ri.setInterfaceConfig(irb.getPostconfig());
		if(ri != null) {
			ri.drawConfigFields(this, table, this, DYNAMIC_FIELD_ID_LIMIT, irb.getId());
		}
    }
	
	/**
	 * This method is used to clean the config-specific GUI widgets. Unlike in the creation, this method just checks if the
	 * Views are identified with ID larger than DYNAMIC_FIELD_ID_LIMIT. If they are, they are config-specific and removed.
	 */
	
	private void removeConfigDependentFields() {
		TableLayout table = (TableLayout)findViewById(R.id.repoconfigtablelayout);
		int childs = table.getChildCount();
		Log.d(TAG,"Num of childs: "+childs);
		for(int i = childs-1; i>=0; i--) {
			View inspectMe = table.getChildAt(i);
			int id = -1;
			String name = null; 
			if(inspectMe != null) {
				id = inspectMe.getId();
				name = inspectMe.toString();
			} else {
				Log.d(TAG,"Config row view was null; Object at : "+i);
			}
			Log.d(TAG,"Found view with id:"+id+", with name:"+name);
			if(id >= DYNAMIC_FIELD_ID_LIMIT) {
				table.removeView(inspectMe);
			}
		}
	}

	public void onClick(View v) {
		EditText username = (EditText)findViewById(R.id.imagerepo_username);
		if(username.getText() == null) {
			AlertUtil.showAlert(this, "Missing information", "Please provide a username which can be used when accessing this repository.");
			return;
		}
		if(username.getText().equals("")) {
			AlertUtil.showAlert(this, "Missing information", "Please provide a username which can be used when accessing this repository.");
			return;
		}
		EditText password = (EditText)findViewById(R.id.imagerepo_password);
		if(password.getText() == null) {
			AlertUtil.showAlert(this, "Missing information", "Please provide a password which can be used when accessing this repository.");
			return;
		}
		if(password.getText().equals("")) {
			AlertUtil.showAlert(this, "Missing information", "Please provide a password which can be used when accessing this repository.");
			return;
		}
		EditText title = (EditText)findViewById(R.id.imagerepo_title);
		if(title.getText() == null) {
			AlertUtil.showAlert(this, "Missing information", "Please provide a title which can be used when accessing this repository.");
			return;
		}
		if(title.getText().equals("")) {
			AlertUtil.showAlert(this, "Missing information", "Please provide a title which can be used when accessing this repository.");
			return;
		}
		String postConfig = null;
		int interfaceType = -1;
		if(ri != null) {
			postConfig = ri.getInterfaceConfig();
			if(postConfig == null) {
				AlertUtil.showAlert(this, "Missing information", "Before you can save this repository configuration, you need to look up an picture album from the service provider."+
				"First enter username and password, then click the \"fetch\" button to look up albums.");
				return;
			}
			interfaceType = ImageRepositoryConstants.getInterfaceTypeId(ri.getRepositoryType());
			Log.d(TAG,"currently Selected repository type:"+interfaceType);
			if(!ImageRepositoryConstants.isGoodType(interfaceType)) {
				AlertUtil.showAlert(this, "Bad repository type", "You have selected a repository type that is not supported by this version of MobiLogger.");
				return;
			}
		}
		if(db == null) {
			db = new DBUtil();
		}
		if(mState == STATE_INSERT) {
			irb = new ImageRepoBean();
			irb.setInterfaceType(interfaceType);
			irb.setPassword(password.getText().toString());
			irb.setPostconfig(postConfig);
			irb.setTitle(title.getText().toString());
			irb.setUsername(username.getText().toString());
			//mainMenuButtonListener.setActivity(this); TODO: ok, think
			if(db.insert(this, irb)) {
					AlertUtil.showAlert(this, "Image repository saved", "Your repository is saved successfully. You can can continue and "+
							"configure other albums or you can exit the image repository configuration.", 
							"Go to main menu", mainMenuButtonListener, 
							"Continue", continueButtonListener);
				return;
			} else {
				AlertUtil.showAlert(this, "Database error", "Error saving your repository. Please check the fields and try again.");
				return;
			}
		} else if(mState == STATE_UPDATE) {
			irb.setInterfaceType(interfaceType);
			irb.setPassword(password.getText().toString());
			irb.setPostconfig(postConfig);
			irb.setTitle(title.getText().toString());
			irb.setUsername(username.getText().toString());
			db.update(this, irb);
		}
		
	}
	
	/**
	 * This listener handles the user's click to "continue with configuration" button on the dialog which is displayed
	 * after saving the image repository configuration.
	 */
	
	DialogInterface.OnClickListener continueButtonListener = new DialogInterface.OnClickListener() {
		
		public void onClick(DialogInterface dialog, int which) {
			dialog.dismiss();
		}
        
    };

    /**
     * This listener handles the user's click to "go to main menu" button on the dialog which is diaplyed after saving the image
     * repository configuration.
     */
    
    DialogInterface.OnClickListener mainMenuButtonListener = new DialogInterface.OnClickListener() {
        
    	Activity parentRef = null;
    	
    	public void onClick(DialogInterface dialog, int which) {
			
		}
    	
    	public void setParentRef(Activity act) {
    		parentRef = act;
		}
        
    };

	
	
}
